home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / DOTHROW.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  12KB  |  474 lines

  1. /*    SCCS Id: @(#)dothrow.c    3.0    89/11/15
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /* Contains code for 't' (throw) */
  6.  
  7. #include "hack.h"
  8.  
  9. static void FDECL(hitfloor, (struct obj *));
  10. static void FDECL(gem_accept, (struct monst *, struct obj *));
  11. static boolean NDECL(martial);
  12. static int FDECL(throw_gold, (struct obj *));
  13. static const char NEARDATA toss_objs[] = { '0', GOLD_SYM, '#', WEAPON_SYM, 0 };
  14. #ifdef WORM
  15. extern boolean notonhead;
  16. #endif
  17.  
  18. int
  19. dothrow() {
  20.     register struct obj *obj;
  21.  
  22.     obj = getobj(toss_objs, "throw");
  23.     /* it is also possible to throw food */
  24.     /* (or jewels, or iron balls... ) */
  25.  
  26.     if(!obj || !getdir(1)) {       /* ask "in what direction?" */
  27.         if(obj && obj->olet == GOLD_SYM) u.ugold += OGOLD(obj);
  28.         return(0);
  29.     }
  30.  
  31.     if(obj->olet == GOLD_SYM) return(throw_gold(obj));
  32.  
  33.     if(!canletgo(obj,"throw"))
  34.         return(0);
  35.     if(obj->otyp == BOULDER
  36. #ifdef POLYSELF
  37.                     && !throws_rocks(uasmon)
  38. #endif
  39.                                 ) {
  40.         pline("It's too heavy.");
  41.         return(1);
  42.     }
  43.     if(!u.dx && !u.dy && !u.dz) {
  44.         You("cannot throw an object at yourself.");
  45.         return(0);
  46.     }
  47.     u_wipe_engr(2);
  48.  
  49.     if(obj == uwep) {
  50.         if(welded(obj)) {
  51.         weldmsg(obj, FALSE);
  52.         return(1);
  53.         }
  54.         if(obj->quan > 1)
  55.         setuwep(splitobj(obj, 1));
  56.         else {
  57.         setuwep((struct obj *)0);
  58.         if (uwep) return(1); /* unwielded, died, rewielded */
  59.         }
  60.     }
  61.     else if(obj->quan > 1)
  62.         (void) splitobj(obj, 1);
  63.     freeinv(obj);
  64.     return(throwit(obj));
  65. }
  66.  
  67. static void
  68. hitfloor(obj)
  69. register struct obj *obj;
  70. {
  71. #ifdef ALTARS
  72.     if (IS_ALTAR(levl[u.ux][u.uy].typ)) doaltarobj(obj);
  73.     else
  74. #endif
  75.         pline("%s hits the floor.", Doname2(obj));
  76.     if (breaks(obj, TRUE)) return;
  77.     else if(obj->olet == POTION_SYM) {
  78.         pline("The flask breaks, and you smell a peculiar odor...");
  79.         potionbreathe(obj);
  80.         obfree(obj, (struct obj *)0);
  81.     } else
  82.         dropy(obj);
  83. }
  84.  
  85. int
  86. throwit(obj)
  87. register struct obj *obj;
  88. {
  89.     register struct monst *mon;
  90.     register int range;
  91.  
  92.     if(u.uswallow) {
  93.         mon = u.ustuck;
  94.         bhitpos.x = mon->mx;
  95.         bhitpos.y = mon->my;
  96.     } else if(u.dz) {
  97.       if(u.dz < 0) {
  98.         pline("%s hits the ceiling, then falls back on top of your %s.",
  99.         Doname2(obj),        /* note: obj->quan == 1 */
  100.         body_part(HEAD));
  101.         if(obj->olet == POTION_SYM)
  102.         potionhit(&youmonst, obj);
  103.         else {
  104.         if(uarmh) pline("Fortunately, you are wearing a helmet!");
  105.         losehp(uarmh ? 1 : rnd((int)(obj->owt)), "falling object",
  106.             KILLED_BY_AN);
  107.         if (!breaks(obj, TRUE)) dropy(obj);
  108.         }
  109.       } else hitfloor(obj);
  110.       return(1);
  111.  
  112.     } else if(obj->otyp == BOOMERANG) {
  113.         mon = boomhit(u.dx, u.dy);
  114.         if(mon == &youmonst) {        /* the thing was caught */
  115.             (void) addinv(obj);
  116.             return(1);
  117.         }
  118.     } else {
  119.         if(shkcatch(obj))
  120.             return(1);
  121.  
  122.         range = (int)((ACURR(A_STR) > 18 ? 20 : ACURR(A_STR))/2 - obj->owt/4);
  123.         if (obj == uball) {
  124.             if (u.ustuck) range = 1;
  125.             else if (range >= 5) range = 5;
  126.         }
  127.         if (range < 1) range = 1;
  128.  
  129.         if ((obj->olet == WEAPON_SYM || obj->olet == GEM_SYM) &&
  130.             uwep &&
  131.             objects[obj->otyp].w_propellor ==
  132.             -objects[uwep->otyp].w_propellor)
  133.                 range++;
  134. #ifdef POLYSELF
  135.         if (obj->otyp == BOULDER) range = 20;
  136. #endif
  137.  
  138.         mon = bhit(u.dx, u.dy, range, obj->olet,
  139.             (int (*)()) 0, (int (*)()) 0, obj);
  140.     }
  141.     if(mon) {
  142.         /* awake monster if sleeping */
  143.         wakeup(mon);
  144. #ifdef WORM
  145.         if(bhitpos.x != mon->mx || bhitpos.y != mon->my)
  146.             notonhead = TRUE;
  147. #endif
  148.         if(thitmonst(mon, obj)) return(1);
  149.     }
  150.     if(!u.uswallow)  {
  151.         char let = obj->olet;
  152.  
  153.         /* the code following might become part of dropy() */
  154.         if (breaks(obj, TRUE)) {
  155.             tmp_at(-1, let);
  156. #ifdef TEXTCOLOR
  157.             tmp_at(-3, (int)objects[obj->otyp].oc_color);
  158. #else
  159.             tmp_at(-3, (int)AT_OBJ);
  160. #endif
  161.             tmp_at(bhitpos.x, bhitpos.y);
  162.             tmp_at(-1, -1);
  163.             return(1);
  164.         }
  165.         if(flooreffects(obj,bhitpos.x,bhitpos.y)) return(1);
  166. #ifdef WORM
  167.         if(obj->otyp == CRYSKNIFE)
  168.             obj->otyp = WORM_TOOTH;
  169. #endif
  170.         obj->nobj = fobj;
  171.         fobj = obj;
  172.         place_object(obj, bhitpos.x, bhitpos.y);
  173.         if(obj != uball && costly_spot(bhitpos.x, bhitpos.y) &&
  174.            !(mon && mon->isshk && bhitpos.x == mon->mx &&
  175.              bhitpos.y == mon->my && !(obj->unpaid)))
  176.             sellobj(obj);
  177.         stackobj(obj);
  178.         if(obj == uball &&
  179.             (bhitpos.x != u.ux || bhitpos.y != u.uy)){
  180.             if(u.utrap){
  181.                 if(u.utraptype == TT_PIT)
  182.                     pline("The ball pulls you out of the pit!");
  183.                 else if(u.utraptype == TT_WEB)  {
  184.                     pline("The ball pulls you out of the web!");
  185.                     pline("The web is destroyed!");
  186.                     deltrap(t_at(u.ux,u.uy));
  187.                 } else {
  188.                 register long side =
  189.                     rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
  190.                 pline("The ball pulls you out of the bear trap.");
  191.                 Your("%s %s is severely damaged.",
  192.                     (side == LEFT_SIDE) ? "left" : "right",
  193.                     body_part(LEG));
  194.                 set_wounded_legs(side, 500+rn2(1000));
  195.                 losehp(2, "leg damage from being pulled out of a bear trap",
  196.                     KILLED_BY);
  197.                 }
  198.                 u.utrap = 0;
  199.             }
  200.             unsee();
  201.             u.ux = bhitpos.x - u.dx;
  202.             u.uy = bhitpos.y - u.dy;
  203.             movobj(uchain,u.ux,u.uy);
  204.             setsee();
  205.             spoteffects();
  206.         }
  207.         if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y);
  208.     }  else
  209.         mpickobj(u.ustuck,obj);
  210.     return(1);
  211. }
  212.  
  213. int
  214. thitmonst(mon, obj)
  215. register struct monst *mon;
  216. register struct obj   *obj;
  217. {
  218.     register int    tmp; /* Base chance to hit */
  219.  
  220.     /* Differences from melee weapons:
  221.      *
  222.      * Dex still gives a bonus, but strength does not.
  223.      * Polymorphed players lacking attacks may still throw.
  224.      * There's a base -2 to hit.
  225.      * No bonuses for fleeing or stunned targets (they don't dodge
  226.      *    melee blows as readily, but dodging arrows is hard anyway).
  227.      * Not affected by traps, etc...
  228.      * Certain items which don't in themselves do damage ignore tmp.
  229.      */
  230.     tmp = -2 + Luck + mon->data->ac;
  231. #ifdef POLYSELF
  232.     if (u.umonnum >= 0) tmp += uasmon->mlevel;
  233.     else
  234. #endif
  235.         tmp += u.ulevel;
  236.     if(ACURR(A_DEX) < 4) tmp -= 3;
  237.     else if(ACURR(A_DEX) < 6) tmp -= 2;
  238.     else if(ACURR(A_DEX) < 8) tmp -= 1;
  239.     else if(ACURR(A_DEX) > 15) tmp += (ACURR(A_DEX) - 15);
  240.  
  241.     if(mon->msleep) {
  242.         mon->msleep = 0;
  243.         tmp += 2;
  244.     }
  245.     if(!mon->mcanmove) {
  246.         tmp += 4;
  247.         if(!rn2(10)) {
  248.             mon->mcanmove = 1;
  249.             mon->mfrozen = 0;
  250.         }
  251.     }
  252.     if (is_orc(mon->data) && pl_character[0]=='E') tmp++;
  253.     if (u.uswallow && mon == u.ustuck) tmp += 1000; /* Guaranteed hit */
  254.  
  255.     if(obj->olet == GEM_SYM && mon->data->mlet == S_UNICORN) {
  256.         if (mon->mtame) {
  257.             kludge("%s catches and drops the %s.",
  258.                 Monnam(mon), xname(obj));
  259.             return(0);
  260.         } else {
  261.             kludge("%s catches the %s.", Monnam(mon), xname(obj));
  262.             gem_accept(mon, obj);
  263.             return(1);
  264.         }
  265.     }
  266.     if(obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE ||
  267.        obj->otyp == UNICORN_HORN || obj->olet == GEM_SYM) {
  268.         if(obj->otyp < DART || obj->olet == GEM_SYM) {
  269.             if (!uwep ||
  270.             objects[obj->otyp].w_propellor !=
  271.             -objects[uwep->otyp].w_propellor)
  272.                 tmp -= 4;
  273.             else    tmp += uwep->spe;
  274.         } else if(obj->otyp == BOOMERANG) tmp += 4;
  275.         tmp += obj->spe;
  276.         tmp += hitval(obj, mon->data);
  277.         if(tmp >= rnd(20)) {
  278.             if(hmon(mon,obj,1) == TRUE){
  279.               /* mon still alive */
  280. #ifdef WORM
  281.               cutworm(mon,bhitpos.x,bhitpos.y,obj->otyp);
  282. #endif
  283.             } else mon = 0;
  284.             /* projectiles thrown disappear sometimes */
  285.             if((obj->otyp < BOOMERANG || obj->olet == GEM_SYM)
  286.                                 && rn2(3)) {
  287.                 /* check bill; free */
  288.                 obfree(obj, (struct obj *)0);
  289.                 return(1);
  290.             }
  291.         } else miss(xname(obj), mon);
  292.     } else if(obj->otyp == HEAVY_IRON_BALL) {
  293.         if(obj != uball) tmp += 2;
  294.         if(tmp >= rnd(20)) {
  295.             if(hmon(mon,obj,1) == FALSE)
  296.                 mon = 0;    /* he died */
  297.         } else miss(xname(obj), mon);
  298.     } else if (obj->otyp == BOULDER) {
  299.         tmp += 6;  /* Likely to hit! */
  300.         if(tmp >= rnd(20)) {
  301.             if(hmon(mon,obj,1) == FALSE)
  302.                 mon = 0;    /* he died */
  303.         } else miss(xname(obj), mon);
  304.     } else if((obj->otyp == CREAM_PIE
  305. #ifdef POLYSELF
  306.             || obj->otyp == BLINDING_VENOM
  307. #endif
  308.                     ) && ACURR(A_DEX) >= rnd(10)) {
  309.         (void) hmon(mon,obj,1); /* can't die from it */
  310. #ifdef POLYSELF
  311.     } else if(obj->otyp == ACID_VENOM && ACURR(A_DEX) >= rnd(10)) {
  312.         if(hmon(mon,obj,1) == FALSE)
  313.             mon = 0;
  314. #endif
  315.     } else if(obj->olet == POTION_SYM && ACURR(A_DEX) >= rnd(15)) {
  316.         potionhit(mon, obj);
  317.         return(1);
  318.     } else {
  319.         pline("The %s misses %s.", xname(obj),
  320.             cansee(bhitpos.x,bhitpos.y) ? mon_nam(mon) : "it");
  321.         if(obj->olet == FOOD_SYM && is_domestic(mon->data))
  322.             if(tamedog(mon,obj)) return(1);
  323.     }
  324.     return(0);
  325. }
  326.  
  327. static void
  328. gem_accept(mon, obj)
  329. register struct monst *mon;
  330. register struct obj *obj;
  331. {
  332.     char buf[BUFSZ];
  333.     static const char NEARDATA nogood[] = " is not interested in your junk.";
  334.     static const char NEARDATA maybeluck[] = " hesitatingly accepts your gift.";
  335.     static const char NEARDATA addluck[] = " graciously accepts your gift.";
  336.  
  337.     Strcpy(buf,Monnam(mon));
  338.  
  339.     mon->mpeaceful = 1;
  340.     if(obj->dknown && objects[obj->otyp].oc_name_known)  {
  341.         if(objects[obj->otyp].g_val > 0)  {
  342.             if(mon->data == &mons[
  343.                 ((u.ualigntyp== U_CHAOTIC) ? PM_BLACK_UNICORN :
  344.                  (u.ualigntyp == U_LAWFUL) ? PM_WHITE_UNICORN
  345.                           : PM_GRAY_UNICORN)]) {
  346.                 Strcat(buf, addluck);
  347.                 change_luck(5);
  348.             } else {
  349.                 Strcat(buf, maybeluck);
  350.                 change_luck(rn2(7)-3);
  351.             }
  352.         } else {
  353.             Strcat(buf,nogood);
  354.             goto nopick;
  355.         }
  356.     }  else  {  /* value unknown to @ */
  357.         change_luck(1);
  358.         Strcat(buf,addluck);
  359.     }
  360.     mpickobj(mon, obj);
  361. nopick:
  362.     if(!Blind) pline(buf);
  363.     rloc(mon);
  364. }
  365.  
  366. /* returns 0 if object doesn't break    */
  367. /* returns 1 if object broke         */
  368. int
  369. breaks(obj, loose)
  370. register struct obj   *obj;
  371. register boolean loose;        /* if not loose, obj is in fobj chain */
  372. {
  373.     switch(obj->otyp) {
  374. #ifdef MEDUSA
  375.         case MIRROR:
  376.             change_luck(-2);    /* and fall through */
  377. #endif
  378.         case EXPENSIVE_CAMERA:
  379.         case CRYSTAL_BALL:
  380.             if(!Blind)
  381.                 pline("%s shatters into a thousand pieces!",
  382.                 Doname2(obj));
  383.             else You("hear something shatter!");
  384.             break;
  385.         case EGG:
  386.             pline("Splat!");
  387.             break;
  388.         case CREAM_PIE:
  389.             pline("What a mess!");
  390.             break;
  391.         case ACID_VENOM:
  392.         case BLINDING_VENOM:
  393.             pline("Splash!");
  394.             break;
  395.         default:
  396.             return 0;
  397.     }
  398.  
  399.     if(loose) {
  400.         unpobj(obj);
  401.         obfree(obj, (struct obj *)0);
  402.     } else {
  403.         addtobill(obj, FALSE);
  404.         delobj(obj);
  405.     }
  406.     return(1);
  407. }
  408.  
  409. static boolean 
  410. martial() 
  411. {
  412.     return((pl_character[0] == 'S' || pl_character[0] == 'P'));
  413. }
  414.  
  415. static int
  416. throw_gold(obj)
  417. struct obj *obj;
  418. {
  419.     int range = 0, odx, ody;
  420.     long zorks = OGOLD(obj);
  421.     register struct monst *mon;
  422.  
  423.     free((genericptr_t) obj);
  424.     if(zorks < 0) {
  425.         /* watch negative overflows a la drop() */
  426.         u.ugold += zorks;
  427.     pline("The LRS would be very interested to know you have that much.");
  428.         return(0);
  429.     }
  430.  
  431.     if(u.uswallow) {
  432.         if (is_animal(u.ustuck->data))
  433.             pline("The gold disappears in the %s's entrails.", 
  434.                   mon_nam(u.ustuck));
  435.         else
  436.             pline("The gold disappears into %s.",
  437.                   mon_nam(u.ustuck));
  438.         u.ustuck->mgold += zorks;
  439.         return(1);
  440.     }
  441.  
  442.     if(u.dz) {
  443.           if(u.dz < 0) {
  444.         pline("The gold hits the ceiling, then falls back on top of your %s.",
  445.             body_part(HEAD));
  446.             /* some self damage? */
  447.             if(uarmh) pline("Fortunately, you are wearing a helmet!");
  448.         } else pline("The gold hits the floor.");
  449.         bhitpos.x = u.ux; /* a msg is needed here */
  450.         bhitpos.y = u.uy;
  451.         goto skip;
  452.     }
  453.  
  454.     range = rnd((int)ACURR(A_STR));
  455.     if(martial()) range = range + rnd(3);
  456.  
  457.     /* see if the gold has a place to move into */
  458.     odx = u.ux + u.dx;
  459.     ody = u.uy + u.dy;
  460.     if(bad_kick_throw_pos(odx,ody)) {
  461.         bhitpos.x = u.ux;
  462.         bhitpos.y = u.uy;
  463.     } else {
  464.         if (mon = ghit(u.dx, u.dy, range))
  465.             if (ghitm(mon, zorks))    /* was it caught? */
  466.             zorks = 0;
  467.     }
  468. skip:
  469.     if (zorks)    /* perhaps it was caught */
  470.         mkgold(zorks, bhitpos.x, bhitpos.y);
  471.     if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y);
  472.     return(1);
  473. }
  474.